/*********************************************************
* 					NL (New Line OS)					 *
*	This OS is made for fun only, although no warrant	 *
*	use it at your own risk.							 *
*														 *
*														 *
*	David												 *
*	2010/04												 *
*														 *
**********************************************************/


#include "SystemNL.h"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/video.cpp"
#include "Types.h"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/keyboard.cpp"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/IRQsHandler.cpp"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/HardDrive.cpp"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/CMOSHandler.h"
#include "C:\Users\David\Desktop\NL\NLProject\Software/NLFileSystem.cpp"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/MouseDriver.cpp"
#include "C:\Users\David\Desktop\NL\NLProject/software\snake.cpp"
#include "C:\Users\David\Desktop\NL\NLProject/Software/drawing.cpp"
#include "C:\Users\David\Desktop\NL\NLProject\Software/StdTimeDate.h"
#include "C:\Users\David\Desktop\NL\NLProject\kernel/kmain.h"
#include "C:\Users\David\Desktop\NL\NLProject\Hardware/APIC.h"
//#include <vector>
//#include <cstring>
//#include <iostream>

template <class type1, class type2>
void showtype(type1 t1, type2 t2)
{
    videomen.printfNL("\n",15);
    videomen.printfNL("\n",15);
    videomen.printfNL("\n",15);
    videomen.printfNL("Type1 is: ",15);
    videomen.printfNL(t1,10);
    videomen.printfNL(" Type2 is: ",15);
    videomen.printfNL(t2,10);
}



using namespace std;

/*
static void *MemoryStart  = (void *)0x20000;
static int MenCounter = 0x20000;

void *operator new(unsigned int size)
{
    int *p;
    int num=0;

    for(; size > 0; size--)
    {
        p = (int *)++MenCounter;
        *p = 0xffffffff;
        if(!*p == 0xfffffff)
        {
            p = 0;
            return p;
        }
        else
        {
            *p = 0;
        }
        num++;

    }
    videomen.printfNL("Allocated bytes: ", 15);
    videomen.printfNL(num,Dec);
    videomen.printfNL("\n",15);
    videomen.printfNL("Mencounter is: ",15);
    videomen.printfNL(MenCounter,Hex);
    videomen.printfNL("\n",15);

    MemoryStart = (void *)MenCounter;
    return MemoryStart;
}


*/

void startup()
{


    cli();

    GDTPtr G_Ptr;
    LDTPtr L_Ptr;
    IDTPtr I_Ptr;

    lgdt(&G_Ptr);
    lidt(&I_Ptr);
    lldt(&L_Ptr);
    CPUControl sel;
    ltr_32(sel.MakeSelector(7,0,0));
    //cli();

    //TSSTables[4].eip = (unsigned int)TimerHandlerIrq;
    //TSSTables[4].cs = 1*8;
    //TSSTables[4].ds = 2*8;
    //TSSTables[4].es = 2*8;
    //TSSTables[4].gs = 2*8;
    //TSSTables[4].fs = 2*8;
    //TSSTables[4].ss = 2*8;
    //TSSTables[4].t = 0;
    //TSSTables[i].ldt_selector = 0;
    //TSSTables[i].ss0 = slctr_gdt_02;
    //TSSTables[3].esp0 = 0x68000;
    //TSSTables[3].esp = 0x68100;
    //TSSTables[4].eflags = 0x3100;
    //Set_NT();
    //Clear_NT();
    //iret();


    Set_Pic();		//set pic for external interrupts

    /*for(unsigned int Avl_Tss = 0;Avl_Tss < TasksAll; Avl_Tss++){
    	TSSTables[0].TableBusy = false;
    }
    TSSTables[0].TableBusy = true; // reserves this table
    TSSTables[1].TableBusy = true; // reserves this table
    TSSTables[2].TableBusy = true; // reserves this table
    TSSTables[3].TableBusy = true; // reserves this table
    */
    videomen.videoInit();

    //PrepareTSS(slctr_gdt_02,0,0,(unsigned int)TaskResume,slctr_gdt_02,slctr_gdt_01,slctr_gdt_02,slctr_gdt_02,slctr_gdt_02,slctr_gdt_02,0,0, &TSSTables[1]);
    //PrepareTSS(slctr_gdt_02,0,0,(unsigned int)TaskResume,slctr_gdt_02,slctr_gdt_01,slctr_gdt_02,slctr_gdt_02,slctr_gdt_02,slctr_gdt_02,0,0, &TSSTables[2]);
    //Clear_NT();    //clears NT

    //asm("lcall $0x38,$000"); // jump

    static Video Scrn, *Screen;
    Screen = &Scrn;

    Screen->printfNL("Please Wait... Loading..",15);

    static CPUID cpu;

    static DiskController HD, *HDD0;// = new DiskController;
    HDD0 = &HD;
    static NLFileSystem FileSytem(HDD0), *FileSys;
    FileSys = &FileSytem;
    static MouseHandler MS, *Mouse;
    Mouse = &MS;
    static CMOSHandler CMH, *Cmos;
    Cmos = &CMH;
    static Keyboard keyboard, *Keyb;
    Keyb = &keyboard;

    Tstorage tm = Cmos->GetTime();
    Dstorage dt = Cmos->GetDate();
    StdTimeDate StringMounth(dt,tm);
    Screen->setXY(7,0);
    Screen->printfNL("Welcome to NL (New Line OS), Now is: ",12);
    Screen->printfNL(StringMounth.GetDateString(),14);
    Screen->printfNL("CPU: ",15);
    Screen->printfNL(cpu.GetString(),15);
    Screen->printfNL("\nThis OS Was Developed For Learning Only, Although No Warrant Use It At Your Own Risk.\n\n",15);



    Cmos->AnableRTCIntrs();
    int men = Cmos->IsntalledMemory();

    Screen->printfNL("\nMemory: ",15);
    Screen->printfNL(men,Dec);
    Screen->printfNL(" KBytes\n",15);
    Screen->printfNL(" Port 40h ",15);
    outb(0x43,0x36);
    outb(0x40,0xff);
    outb(0x40,0xff);



    //Cmos->wait(100);  //project

    static draw dw;
    //dw.drawi();
    dw.Box(25 / 2, 80 / 2,10,tm.Sec.i);
    dw.Box(25 / 3, 80 / 2 + 7,10,tm.Sec.i);
    dw.Box(16, 80 / 2 + 7,8,tm.Sec.i);
    dw.Box(25 / 2, 80 / 2 + 14,10,tm.Sec.i);

    static TaskCreate task;

    //TSSTables[0].prev_task_link = sel.MakeSelector(14,0,3);

    task.createTask((unsigned int *)Task2,1);
    task.createTask((unsigned int *)Task3,2);



    //showtype(30,30);



    //asm("int %0":: "i"(1));
    // asm("movl %0, %1" :: "r" (test), "a"(4) );
    // asm("movl %eax,%dr0");
    //Set_Trap();


   // asm("lcall %0, $0" : : "i" (15 * 8));
    //asm("lcall %0, $0" : : "i" (slctr_gdt_14));


    Apic api;

    //api.SetTimer(100,45);

    //DisableRTCIntrs();
    //Keyboard *keybp, MouseHandler *mousep, CMOSHandler *Cmosp, DiskController *HDD0p, NLFileSystem *filesysp
    sti();
    static NLMain NL(Keyb,Mouse,Cmos,HDD0,FileSys);

    NL.start();



}




/*static void TaskHandler(unsigned int Task){
	Save_Context();
		//if(!TaskExist(Task)){// if task does not exist, then give it a table and and set busy
		//TaskInit(Task);
		//}

	asm("call * %0" :: "r" (Task));

		//if(TSSTables[2].Finished){

		//	videomen.videomen.printfNL("Task f",4);

		//}else{
		//videomen.videomen.printfNL("Task R",4);
		//Tss_Cpy(&TSSTables[2], &TSSTables[3]);

	//	}



}*/


static void Task2()
{

    for(int i =0; i < 1000; i++)
    {
        static char *video = (char *)0xB8000;
        static char *msg = " Taskssssssssssssss 2";

        while(*msg != 0)
        {
            *video++ = *msg++;
            video++;
        }

        int teste;

        for(int i =0xFF;i;i--)
        {
            teste = i;
        }
        //asm("lcall %0, $0" : : "i" (slctr_gdt_14), "i" (0));

    }

    iret();
}
static void Task3()
{
    static char *video3 = ((char *)0xB8000 + 80 * 2 * 4);
    static char *msg3 = "   Taskssssssssssssss 33333";

    while(*msg3 != 0)
    {
        *video3++ = *msg3++;
        *video3++ = 15;
    }

    for(int i =0;i; i++) {} //asm("sti");}

    iret();
}




/*	static void Tss_Cpy(Tss_32 *From, Tss_32 *To){

	To-> prev_task_link = From->prev_task_link;
	To-> esp0 = From->esp0;
	To-> ss0 = From->ss0;
	To-> esp1 = From->esp1;
	To-> ss1 = From->ss1;
	To-> esp2 = From->esp2;
	To-> ss2 = From->ss2;
	To-> cr3 = From->cr3;
	To-> eip = From->eip;
	To-> eflags = From->eflags;
	To-> eax = From->eax;
	To-> ecx = From->ecx;
	To-> edx = From->edx;
	To-> ebx = From->ebx;
	To-> esp = From->esp;
	To-> ebp = From->ebp;
	To-> esi = From->esi;
	To-> edi = From->edi;
	To-> es = From->es;
	To-> cs = From->cs;
	To-> ss = From->ss;
	To-> ds = From->ds;
	To-> fs = From->fs;
	To-> gs = From->gs;
	To-> ldt_selector = From->ldt_selector;
	To-> t = From->t;
	To-> io_map = From->io_map;
	}*/

static void lgdt(GDTPtr *G_Ptr)
{
    CPUControl sel;
    //entry,  	                            limit,       		base,                     type,                            flags,
    Set_GDT_Entry(&GDTEntries[0], 	        0,           	 0,                        0,                               0, 0x0);
    Set_GDT_Entry(&GDTEntries[1], 	      0xffffffff,        0,                     prsnt_rng0_code_er_naccssd,      0xc0, 0x0a);
    Set_GDT_Entry(&GDTEntries[2], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0, 0xf);	//ds
    Set_GDT_Entry(&GDTEntries[3], 	      0xffffffff,        0,                		prsnt_rng0_data_rw_naccssd,      0xc0, 0xf); //es
    Set_GDT_Entry(&GDTEntries[4], 	      0xffffffff,        0,                		prsnt_rng0_data_rw_naccssd,      0xc0, 0xf); //gs
    Set_GDT_Entry(&GDTEntries[5], 	      0xffffffff,        0,                		prsnt_rng0_data_rw_naccssd,      0xc0, 0xf); //fs
    Set_GDT_Entry(&GDTEntries[6], 	      0xffffffff,       0xB8000,                prsnt_rng0_data_rw_naccssd,     0xc0, 0xf); //video seg not used
    Set_GDT_Entry(&GDTEntries[7], 	      0x67,       (unsigned int)&TSSTables[0],             tss_p_rng0,     	 0x0, 0x0); //tss seg
    Set_GDT_Entry(&GDTEntries[8], 	      0x67,       (unsigned int)&TSSTables[1],             tss_p_rng0,     		 0x0, 0x0); //tss seg
    Set_GDT_Entry(&GDTEntries[9], 	      0xffffffff,       0,              prsnt_rng3_code_er_naccssd,     0xc0, 0xf); //code
    Set_GDT_Entry(&GDTEntries[10], 	      0xffffffff,       0,              prsnt_rng3_data_rw_naccssd,     0xc0, 0xf); //data
    Set_GDT_Entry(&GDTEntries[11], 	      0xffffffff,       0,              prsnt_rng3_stck_rw_naccssd,     0xc0, 0xf); //data
    Set_GDT_Entry(&GDTEntries[12], 	      0xffffffff,       0,              prsnt_rng3_stck_rw_naccssd,     0xc0, 0xf); //data
    Set_GDT_Entry(&GDTEntries[13], 	      0xffffffff,       0,              prsnt_rng3_stck_rw_naccssd,     0xc0, 0xf); //data
    Set_GDT_Entry(&GDTEntries[14], 	      0x67,       	(unsigned int)&TSSTables[2],             tss_p_rng0,     		 0x0, 0x0); //tss seg
    Set_GDT_Entry(&GDTEntries[15], 	      0,       	sel.MakeSelector(8,0,0),             tskgt_rng0,     		 0, 0); //tss seg
    Set_GDT_Entry(&GDTEntries[16], 	      0xffffffff,       	0,             prsnt_rng3_code_er_naccssd,     		 0xc, 0); //tss seg
    Set_GDT_Entry(&GDTEntries[17], 	      (sizeof LDTEntries / 8)* 8,       (unsigned int)&LDTEntries,                     prsnt_rng0_code_er_naccssd,      0xc0, 0x0);
    Set_GDT_Entry(&GDTEntries[18], 	      0xffffffff,       0,                     prsnt_rng0_code_er_naccssd,      0xc0, 0xf);
    Set_GDT_Entry(&GDTEntries[19], 	      0xffffffff,       0,                     callgt_rng3,      0xc0, 0xf);
    //Set_GDT_Entry(&GDTEntries[20], 	      0x67,       	(unsigned int)&TSSTables[4],             tss_p_rng0,     		 0x0, 0x0); //timer



    SetGDTPtr(G_Ptr);


    asm("lgdt %0" :: "m" (*G_Ptr));

    asm("pushl %eax\n"
        "movl  	%cr0, %eax\n"
        "bts    $1, %eax\n"
        "movl  	%eax,%cr0\n"
        "ljmp   $0x08,$flush  \n"
        "flush:	\n"
        "movw	$0x10,%ax\n"
        "movw	%ax,%ds\n"
        "movw	%ax,%ss\n"
        "movw	$0x18,%ax\n"
        "movw	%ax,%es\n"
        "movw	$0x20,%ax\n"
        "movw	%ax,%gs\n"
        "movw	$0x28,%ax\n"
        "movw	%ax,%fs\n"
        //"movl	$80000,%eax\n"
        //"movl	%eax,%esp\n"
        "popl   %eax\n"
       );
}
static void lldt(LDTPtr *L_Ptr)
{

    //entry,      limit,       		base,                     type,                            flags,
    Set_LDT_Entry(&LDTEntries[0], 	      0xffffffff,        0,                     prsnt_rng0_code_er_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[1], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[2], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[3], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[4], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[5], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);
    Set_LDT_Entry(&LDTEntries[6], 	      0xffffffff,        0,                     prsnt_rng0_data_rw_naccssd,      0xc0);

    SetLDTPtr(L_Ptr);

    //asm("lldt %0" :: "m" (*L_Ptr));

    asm("lldt %w0" :: "r" (0 * 8)); ////////Correct this slctr_gdt_00

}

static void lidt(IDTPtr *I_Ptr)
{
    CPUControl Sel;
                        //Entry,                offset,                        selector,           type,        undef
    Set_IDT_Entry(&IDTEntries[0],              (unsigned int)divideerror,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //divide error
    Set_IDT_Entry(&IDTEntries[1],              (unsigned int)debugexceptions,    		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //debug exceptions
    Set_IDT_Entry(&IDTEntries[2],              (unsigned int)nonmaskableinterrupt,   	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //nonmaskable interrupt
    Set_IDT_Entry(&IDTEntries[3],              (unsigned int)breakpoint,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //breakpoint
    Set_IDT_Entry(&IDTEntries[4],              (unsigned int)overflow,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //overflow (into instruction)
    Set_IDT_Entry(&IDTEntries[5],              (unsigned int)boundscheck,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //bounds check (bound instruction)
    Set_IDT_Entry(&IDTEntries[6],              (unsigned int)invalidopcode,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //invalid opcode
    Set_IDT_Entry(&IDTEntries[7],              (unsigned int)coprocessoravailable,  	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //coprocessor not available
    Set_IDT_Entry(&IDTEntries[8],              (unsigned int)doublefault,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //double fault
    Set_IDT_Entry(&IDTEntries[9],              (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[10],             (unsigned int)invalidtss,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //invalid tss
    Set_IDT_Entry(&IDTEntries[11],             (unsigned int)segmentnotpresent,      	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //segment not present
    Set_IDT_Entry(&IDTEntries[12],             (unsigned int)stackexception,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //stack exception
    Set_IDT_Entry(&IDTEntries[13],             (unsigned int)generalprotection,     	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //general protection
    Set_IDT_Entry(&IDTEntries[14],             (unsigned int)pagefault,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //page fault
    Set_IDT_Entry(&IDTEntries[15],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[16],             (unsigned int)coprecessorerror,       	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //coprecessor error
    Set_IDT_Entry(&IDTEntries[17],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[18],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[19],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[20],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[21],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[22],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[23],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[24],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[25],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[26],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[27],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[28],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[29],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[30],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[31],             (unsigned int)Handler,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //(reserved)
    Set_IDT_Entry(&IDTEntries[32],             (unsigned int)TimerHandlerIrq,      	   	Sel.MakeSelector(18,0,0),     intrrgt_rng0, 	0); //timer
    Set_IDT_Entry(&IDTEntries[33],             (unsigned int)KeyboardHandlerIrq,       	Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //keyboard
    Set_IDT_Entry(&IDTEntries[34],             (unsigned int)ChipHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //cascaded
    Set_IDT_Entry(&IDTEntries[35],             (unsigned int)Serial2HandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //serial2
    Set_IDT_Entry(&IDTEntries[36],             (unsigned int)Serial1HandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //serial1
    Set_IDT_Entry(&IDTEntries[37],             (unsigned int)FreeHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //lpt
    Set_IDT_Entry(&IDTEntries[38],             (unsigned int)FloppyHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //floppy
    Set_IDT_Entry(&IDTEntries[39],             (unsigned int)LPTHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //lpt1
    Set_IDT_Entry(&IDTEntries[40],             (unsigned int)CmosClockHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //realtime
    Set_IDT_Entry(&IDTEntries[41],             (unsigned int)VideoHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //cascateirq9
    Set_IDT_Entry(&IDTEntries[42],             (unsigned int)Free2HandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //irq10
    Set_IDT_Entry(&IDTEntries[43],             (unsigned int)USBHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //irq11
    Set_IDT_Entry(&IDTEntries[44],             (unsigned int)PS2MouseHandlerIrq,       		Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //mouse
    Set_IDT_Entry(&IDTEntries[45],             (unsigned int)CoProcHandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //coprocessor
    Set_IDT_Entry(&IDTEntries[46],             (unsigned int)ATA1HandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //FirstATA
    Set_IDT_Entry(&IDTEntries[47],             (unsigned int)ATA2HandlerIrq,       			Sel.MakeSelector(18,0,0),     intrrgt_rng0,    0); //secondaryata
    Set_IDT_Entry(&IDTEntries[48],             				0,       					Sel.MakeSelector(8,0,0),     tskgt_rng0,      0);

    SetIDTPtr(I_Ptr);

    asm("lidt %0" :: "m" (*I_Ptr));

}

static void SetGDTPtr(GDTPtr *Ptr)
{
    Ptr->size = ((sizeof GDTEntries / 8 - 1)* 8);
    Ptr->addrs = (unsigned int)&GDTEntries;
}

static void SetLDTPtr(LDTPtr *Ptr)
{
    Ptr->size = ((sizeof LDTEntries / 8)* 8);
    Ptr->addrs = (unsigned int)&LDTEntries;
}

static void SetIDTPtr(IDTPtr *Ptr)
{
    Ptr->size = ((sizeof IDTEntries / 8)* 8);
    Ptr->addrs = (unsigned int)&IDTEntries;
}

static void	Set_GDT_Entry(GDTEntry *Entry, unsigned short limit, unsigned int base,
                          unsigned char type, unsigned char flags, unsigned char limithigh)
{
    unsigned char  limitflag = 0;
    //limitflag = (limitflag >>0| (flags & 0xF0));
    limitflag = ((limithigh & 0x0F) | (flags & 0xF0));//join

    Entry->base_31_24 = (base >> 24);
    Entry->base_23_16 = (base >> 16);
    Entry->base = base;
    Entry->type = type;
    Entry->limit = limit;
    Entry->flags = limitflag;

}

static void	Set_LDT_Entry(LDTEntry *Entry, unsigned int limit, unsigned int base,
                          unsigned char type, unsigned char flags)
{

    unsigned short basetmp;
    unsigned char  base_23_16tmp;
    unsigned char  base_31_24tmp;
    unsigned short limittmp;
    unsigned char  limitflag;
    basetmp = (base >> 0); //basetmp is the low order 16 bits of base
    base_23_16tmp = (base >> 16);//base_23_16 is the 16 to 23 of base var
    base_31_24tmp = (base >> 24);//base_31_24 is bits 24 to 31 of base var
    limittmp =    (limit >> 0); //limittmp is the low order 16 bits of limit
    limitflag =   (limit >> 12); //limitflag we'll use bits 16 to 19
    limitflag =   (limitflag >> 4); //limitflag we'll clear the up 4 bits
    limitflag =   (flags | limitflag);//join
    Entry->limit = limittmp;
    Entry->base = basetmp;
    Entry->base_23_16 = base_23_16tmp;
    Entry->type = type;
    Entry->flags = limitflag;
    Entry->base_31_24 = base_31_24tmp;
}

static void	Set_IDT_Entry(IDTEntry *Entry, unsigned int offset, unsigned short selector,
                          unsigned char type , unsigned char undef)
{

    unsigned short offsettmp_15_0;
    unsigned short offsettmp_31_16;
    offsettmp_15_0 = (offset >> 0); //take 16 bit of the offset
    offsettmp_31_16 =(offset >> 16);//the rest of bits
    Entry->offset_15_0 = offsettmp_15_0;
    Entry->selector = selector;
    Entry->undef = undef;
    Entry->type = type;
    Entry->offset_31_16 = offsettmp_31_16;

}

static void ltr_32(unsigned short int Selctr)
{
    asm volatile("ltr %0" :: "r" (Selctr)); // load tss selector from ax register
}



/*
static void PrepareTSS(
	unsigned short ss0,
	unsigned short ss1,
	unsigned short ss2,
	unsigned int eip,
	unsigned short es,
	unsigned short cs,
	unsigned short ss,
	unsigned short ds,
	unsigned short fs,
	unsigned short gs,
	unsigned short  t,
	unsigned short io_map,
	Tss_32 *Tss){
	Tss->ss0 = ss0;
	Tss->ss1 = ss1;
	Tss->ss2 = ss2;
	Tss->eip = eip;
	Tss->eflags = 0;
	Tss->es = es;
	Tss->cs = cs;
	Tss->ss = ss;
	Tss->ds = ds;
	Tss->fs = fs;
	Tss->gs = gs;
	Tss->t = t;
	Tss->io_map = io_map;
}*/

static void	Set_Pic()
{
    outb(mastersecprt,0xff);
    outb(slavesecprt,0xff);
    outb(masterfsprt,icw1);
    outb(slavefsprt,icw1);
    outb(mastersecprt,icw2);
    outb(slavesecprt,icw2s);
    outb(mastersecprt,icw3);
    outb(slavesecprt,icw3s);
    outb(mastersecprt,icw4);
    outb(slavesecprt,icw4);
    //-----------------------
    outb(masterfsprt,0x0b);
    outb(slavefsprt,0x0b);
    outb(mastersecprt,0x00);
    outb(slavesecprt,0x00);


}

static void Handler()
{
    Isr_Enter();
    videomen.printfNL("NL Handler",46);
    Isr_Exit();
}

static void divideerror()
{
    videomen.printfNL("Divide Error", 12);
    iret();
}

static void debugexceptions()
{
    debugex++;
    iret();
}
static void nonmaskableinterrupt()
{
    videomen.printfNL("Non-Maskeble",10);
    iret();
}

static void breakpoint()
{
    videomen.printfNL("\nBreak Point",9);
    //for(;;) {}
    iret();
}

static void overflow()
{
    videomen.printfNL("over Flow",6);
    iret();
}

static void boundscheck()
{
    videomen.printfNL("Bounds",14);
    iret();
}

static void invalidopcode(unsigned short arg)
{
    videomen.printfNL("\nInvalid Opcode: ",12);
    videomen.printfNL(arg,Hex);
    videomen.printfNL("\n",15);
    arg = (unsigned int)&Task2;
}

static void coprocessoravailable()
{
    videomen.printfNL("Ex. Coprocessor",8);
    iret();
}

static void doublefault()
{
    videomen.printfNL("Double Fault",8);
    iret();
}

static void invalidtss(unsigned int arg)
{
    //videomen.cls();
    videomen.printfNL("\n\n\n\n\n\n\n\n\n\nInvalid TSS: ",12);
    videomen.printfNL(arg,Hex);
    static ShowTssTables table;
    table.ShowTables(&TSSTables[0]);
    //table.ShowTables(&TSSTables[1]);
    //table.ShowTables(&TSSTables[2]);
    //for(;;){}
    iret();
}

static void segmentnotpresent()
{
    videomen.printfNL("Seg Not Present",45);
    iret();
}

static void stackexception()
{
    videomen.printfNL("Stack Excep.",32);
    iret();
}

static void generalprotection(unsigned int arg)
{

    videomen.printfNL("\nGeneral Protection fault Code: ",12);
    videomen.printfNL(arg,Hex);
    arg = (unsigned int)&Task2;
    //sti();
    //for(;;) {}
    iret();
}

static void pagefault()
{
    videomen.printfNL("Page Fault",07);
    iret();
}

static void coprecessorerror()
{
    videomen.printfNL("Co-proc Error",04);
    iret();
}


static void TimerHandler()
{
    //videomen.videomen.printfNL("timer",78);
    /*	static int i = 0;
    	i++;
    	if(i == 3){i = 0;};
    	char wheel[] = {'\\', '|', '/', '-'};

    	videomen.printchar(&wheel[i]);
    */
}


